package domain;

import control.ExpenseManager;
import utils.CommandAnalyzer;
import utils.DataFormat;
import enums.Frequency;
import basic.Date;

//@author A0098891H
public class Budget {
	
	private double _maxAmount;
	private double _amount; 
	private Date _dateStart;
	private Frequency _freq;
	private boolean _isOn;
	/**
	 * @param freq
	 */
	public Budget(Frequency freq)
	{
		_freq = freq;
		_maxAmount = 0;
		_amount = 0;
		_isOn = false;
	}
	
	// Budget constructor used to call InvestmentPlanPanel of MainGUI
	/**
	 * @param freq
	 * @param amount
	 */
	public Budget(Frequency freq, double amount) {
		_freq = freq;
		_maxAmount = 0;
		_amount = amount;
		_isOn = false;
		_dateStart = Date.getCurrentDate();
	}
	
	/**
	 * 
	 * @Precondition 
	 * @Postcondition 
	 */
	public void turnOff()
	{
		_isOn = false;
		_amount = 0;
		_maxAmount = 0;
	}

	/**
	 * 
	 * @return
	 * @Precondition 
	 * @Postcondition 
	 */
	public boolean isOn() {
		return _isOn;
	}
	/**
	 * 
	 * @Precondition 
	 * @Postcondition 
	 */
	public void turnOn() {
		 _isOn = true;
		_dateStart = Date.getCurrentDate();
	}
	
	// Return value of _amount, to be used in SavingsCalculator
	/**
	 * 
	 * @return
	 * @Precondition 
	 * @Postcondition 
	 */
	public double get_totalBalance() {
		return this._amount;
	}
	
	/**
	 * update(reset) the budget after certain period
	 * @return true if updated successfully, false, when the budget is not on.
	 * @Precondition no
	 * @Postcondition the budget updated
	 */
	public boolean getLastStartDate()
	{

		//if current date - datestart > currentDay/currentWeek/currentMonth/currentYear
		//clear amount and reset date to next checkDate
		//return true. 
		switch(_freq)
		{
		case DAILY:
			if(Date.getCurrentDate().isGreaterOrEqual(_dateStart.getRelatedDate(0, 0, 0, 1)))
			{
				_dateStart = Date.lastDateAccordingly(_dateStart, Frequency.DAILY);
//				System.out.println("daily updated to " +_dateStart);
				return true;
			}
			break;
		case WEEKLY:
			if(Date.getCurrentDate().isGreaterOrEqual(_dateStart.getRelatedDate(0, 0, 1, 0)))
			{
				_dateStart = Date.lastDateAccordingly(_dateStart, Frequency.WEEKLY);
//				System.out.println("weekly updated to " +_dateStart);
				return true;
			}
			break;
		case MONTHLY:
			if(Date.getCurrentDate().isGreaterOrEqual(_dateStart.getRelatedDate(0, 1, 0, 0)))
			{
				_dateStart = Date.lastDateAccordingly(_dateStart, Frequency.MONTHLY);
//				System.out.println("monthly updated to " +_dateStart);
				return true;
			}
			break;
		case YEARLY:
			if(Date.getCurrentDate().isGreaterOrEqual(_dateStart.getRelatedDate(1, 0, 0, 0)))
			{
				_dateStart = Date.lastDateAccordingly(_dateStart, Frequency.YEARLY);
//				System.out.println("yearly updated to " +_dateStart);
				return true;
			}
			break;
		default:
			break;
		}
		return false;
	}
	
	public boolean updateBudget(ExpenseManager xpnMan)
	{
		if(!_isOn)
			return false;

		getLastStartDate();
		
		this._amount = _maxAmount;

		for(Expense xpn: xpnMan.getList())
		{
			updateNoFreq(xpn,_freq);
		}

		return true;
	}
	
	//if the Expense has no frequency
	public void updateNoFreq(Expense xpn, Frequency freq)
	{//just deduct once if it is within the range. if its created date between the budget startDate and budget endDate
		int year, month, week, day;
		switch(freq)
		{
		case NO:
			year = month = week = day = 1;
			break;
		case DAILY:
			year = month = week = 0;  day = 1;
			break;
		case WEEKLY:
			year = month = day = 0;  week = 1;
			break;
		case MONTHLY:
			year = day = week = 0;  month = 1;
			break;
		case YEARLY:
			day = month = week = 0;  year = 1;
			break;
		default:
			year = month = week = day = 0;
			break;
			
		}
		
		if(xpn.get_frequency()==Frequency.NO)
		{
			Date createdDate = xpn.get_date();
//			System.out.println(xpn.get_name()+" "+createdDate + " "+_dateStart+ " "+_dateStart.getRelatedDate(year, month, week, day));
			if(createdDate.isGreaterOrEqual(_dateStart)
					&&createdDate.isLessThan(_dateStart.getRelatedDate(year, month, week, day)))
			{
				_amount -= xpn.get_amount();
			}
		}
	}
	
	
	/**
	 * 
	 * @param amount
	 * @param startDate
	 * @Precondition 
	 * @Postcondition 
	 */
	public void set(double amount, Date startDate)
	{//need to update the amount
		if(amount>0)
		{
			_isOn = true;
			_dateStart = startDate;
		}
		else
		{
			_isOn = false;
		}
		this._maxAmount = amount;
		this._amount = _maxAmount;
//		updateBudget();
	}
	
	/**
	 * 
	 * @param amount
	 * @Precondition 
	 * @Postcondition 
	 */
	public void set(double amount)
	{//need to update the amount
		if(amount>0)
		{
			_isOn = true;
		}
		else
		{
			_isOn = false;
		}
		this._maxAmount = amount;
		this._amount = _maxAmount;
//		updateBudget();
	}
	
	// set current budget with amount parameter only, to be used in SavingsCalculator
	/**
	 * 
	 * @param amount
	 * @Precondition 
	 * @Postcondition 
	 */
	public void set_currentBudget(double amount) {
		this._amount = amount;
	}

	/**
	 * 
	 * @param startDate
	 * @Precondition 
	 * @Postcondition 
	 */
	public void set_startDate(Date startDate)
	{
		if(!startDate.toString().equals(Date.NA_DATE))
			_dateStart = startDate;
	}
	/**
	 * 
	 * @return
	 * @Precondition 
	 * @Postcondition 
	 */
	public Date get_startDate()
	{
		return _dateStart;
	}
	
	/**
	 * 
	 * @param amount
	 * @Precondition 
	 * @Postcondition 
	 */
	public void set_maxAmount(double amount)
	{
		this._maxAmount = amount;
	}
 
	/**
	 * 
	 * @return
	 * @Precondition 
	 * @Postcondition 
	 */
	public double get_maxAmount() {
		return _maxAmount;
	}
	
	/**
	 * 
	 * @return
	 * @Precondition 
	 * @Postcondition 
	 */
	public double get_amount() {
		return _amount;
	}

	
	// Subtract amount to be used in SavingsCalculator
	/**
	 * 
	 * @param amount
	 * @Precondition 
	 * @Postcondition 
	 */
	public void subtractAmount(double amount) {
		this._amount -= amount;
	}
	
	/**
	 *
	 * @see java.lang.Object#toString()
	 * @return
	 * @Precondition 
	 * @Postcondition 
	 */
	public String toString()
	{
		if(_isOn)
		{
			return "  "+_freq+": On. "+_amount + "/"+ _maxAmount +" "+ _dateStart.toString() +"\n";
		}
		else
		{
			return "  "+_freq+": Off. " +"\n";
		}
	}
	
	/**
	 * 
	 * @return
	 * @Precondition 
	 * @Postcondition 
	 */
	public String writeToString()
	{
		return _freq+ "," + _maxAmount +"," + CommandAnalyzer.PARAM_DATE + _dateStart;
	}
	
	public String printStatus()
	{
		if(_isOn)
			return  "    "+_freq+" Budget: "+ DataFormat.returnTwoDecimals(_amount) + "/"+ DataFormat.returnTwoDecimals(_maxAmount) +"\n";
		else
			return "";
	}
	
}
